/* ======================================================================================== *\

		FILE:				InstancedForwardRenderer.h
		AUTHOR:				Jack Hoxley

		DESCRIPTION:		An implementation of traditional forward rendering using
							geometry instancing for more efficient rendering.

		CHANGE:				27th August 2007
								Defined basic interface
								Moved constants to Constants.h
							8th September 2007
								Modified 'InstancedVertex' struct to include normals

\* ======================================================================================== */

#ifndef INC_INSTANCEDFORWARDRENDERER_H
#define INC_INSTANCEDFORWARDRENDERER_H

// Include Standard Headers
// ------------------------
#include "DXUT.h"



// Include project headers
// -----------------------
#include "Utils.h"
#include "Profiling.h"
#include "PipeLayout.h"
#include "PipeRenderer.h"



namespace Renderer
{
	struct InstancedVertex
	{
		D3DXVECTOR3 p;
		D3DXVECTOR3 n;
		float blend_weight;
	};

	struct InstancedData
	{
		float segment_weight;
		D3DXMATRIX blend_from;
		D3DXMATRIX blend_to;
	};


	class InstancedForwardRenderer : public PipeRenderer
	{
		public:
			// Constructors
			// ============
			InstancedForwardRenderer( );
			~InstancedForwardRenderer( );

			// Required operations
			// ===================
			HRESULT CreateResources( ID3D10Device* pDevice, const PipeSim::PipeLayout * const p );
			HRESULT UpdateResources( const PipeSim::PipeLayout * const p );
			HRESULT DestroyResources();

			HRESULT Render( ID3D10Device* pDevice, D3DXMATRIX& mViewProj );

			UINT32 VideoMemoryStorageInUse();
			void RendererName( wchar_t* wcDestination, const size_t& DestinationSize );

			// Additional operations
			// =====================

		private:
			// Following standard operations don't really have
			// a useful meaning in the context of this class
			InstancedForwardRenderer( const InstancedForwardRenderer& copy );
			bool operator == ( const InstancedForwardRenderer& rhs );
			InstancedForwardRenderer& operator = ( const InstancedForwardRenderer& rhs );

			// Rendering related members
			ID3D10Effect* m_pEffect;

			ID3D10Buffer* m_pVertexBuffer;
			ID3D10Buffer* m_pIndexBuffer;

			ID3D10EffectTechnique* m_pTechnique;
			ID3D10InputLayout** m_ppInputLayouts;

			UINT32 m_VertexCount;
			UINT32 m_IndexCount;

			struct PipeResources
			{
				ID3D10Buffer*	m_pPerInstanceData;
				UINT32			m_LastUpdated;
				
				UINT32			m_PipeLength;
			};

			UINT16 m_PipeCount;
			PipeResources** m_ppPipe;

			// General statistics
			UINT32 m_VRAMUsage;

			// Private member functions:
			HRESULT CreatePipeGeometry( ID3D10Device* pDevice, const UINT16& xSize, const UINT16& ySize, const UINT16& zSize );
			void CreatePipeVertexData( D3D10_SUBRESOURCE_DATA* p, const float& height, const float& width );
			void CreatePipeIndexData( D3D10_SUBRESOURCE_DATA* p );

			HRESULT UpdateIndividualPipe( PipeResources* p, const Utils::CoordinateList& coords, const UINT16& xSize, const UINT16& ySize, const UINT16& zSize, const UINT32& CurrLen );
			D3DXMATRIX GetRotationMatrixForVector( const Utils::IntegerVector& vec );
	};
};

#endif // INC_INSTANCEDFORWARDRENDERER_H